package com.kk.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

/**
 * the class of spring_security_demo
 * <p>
 * 开启方法级别的安全认证机制。prePostEnabled = true： 开启 @PreAuthorize, @PostAuthorize 功能；
 * <p>
 * .
 *
 * @author little_lunatic
 * @date 2023-05-30
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /** 认证成功结果处理器 */
    private final AuthenticationSuccessHandler loginSuccessHandler;

    /** 认证失败结果处理器 */
    private final AuthenticationFailureHandler loginFailureHandler;

//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        /**
//         * 基于内存的方式，创建两个用户admin/123456，root/123456
//         * */
//        auth.inMemoryAuthentication()
//                .withUser("admin")
//                .password(passwordEncoder().encode("123456"))
//                .roles("ADMIN");
//
//        auth.inMemoryAuthentication()
//                .withUser("root")
//                .password(passwordEncoder().encode("123456"))
//                .roles("ROOT");
//    }

    /**
     * 解决springboot配置spring security 静态资源不能访问
     *
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        // 配置静态文件不需要认证
        web.ignoring().antMatchers("/static/**");
        web.ignoring().antMatchers("/templates/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().permitAll()
//                .antMatchers("/doc.html", "/v3/api-docs", "/swagger-ui.html", "/webjars/**", "/swagger-resources/**").permitAll()
                .and().csrf().disable();
    }

//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http.headers().frameOptions().disable(); // 开启运行 iframe 嵌套页面
//
//        // 1.配置权限
//        http.authorizeRequests()
//                // 配置不拦截路由
//                .antMatchers("500").permitAll()
//                .antMatchers("404").permitAll()
//                .antMatchers("403").permitAll()
//                .antMatchers("/login").permitAll()
//                // 其他任何请求都要认证
//                .anyRequest().authenticated()
//                .and()
//                // 2.配置登录表单认证方式,自定义登录页面url、登录名参数名、密码参数名，与表单参数名保持一致
////                .formLogin().loginPage("/login").usernameParameter("name").passwordParameter("password")
//                // 配置默认登录入口、登录成功后默认的跳转页面路径、
////                .loginProcessingUrl("/user/login").defaultSuccessUrl("/index").failureUrl("/user?error=true")
//                // 用自定义的成功、失败结果处理器
////                .successHandler(loginSuccessHandler).failureHandler(loginFailureHandler)
////                .and()
//                // 3.注销
//                .logout().logoutUrl("/logout").permitAll()
//                .and()
//                // 4.session管理
//                .sessionManagement()
//                //失效后跳转到登陆页面
//                .invalidSessionUrl("/login")
//                //单用户登录，如果有一个登录了，同一个用户在其他地方登录将前一个剔除下线
//                .maximumSessions(1).expiredSessionStrategy(sessionInformationExpiredEvent -> {
//                    System.out.println("您已下线，在其他设备登录");
//                });
//        //单用户登录，如果有一个登录了，同一个用户在其他地方不能登录
//        //.maximumSessions(1).maxSessionsPreventsLogin(true);
//
//
//    }

    /**
     * 使用 BCrypt 加密密码
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }



}
